import FileSelectInput from "@/components/FileSelectInput";
import { command } from "@/config/api";
import type {
  CommonSettings,
  DBSettings,
  GatewaySettings,
  LogSettings,
  SettingKey,
  Settings,
  SettingValue
} from "@/type";
import { Box, Button, Checkbox, Divider, FormControlLabel, TextField } from "@mui/material";
import { OverlayScrollbarsComponent } from "overlayscrollbars-react";
import { invoke } from "@tauri-apps/api/core";
import Toast from "@/components/Toast";

function SettingLayout({ title, children }: { title: string; children?: React.ReactNode }) {
  return (
    <Box
      sx={{
        display: "flex",
        flexDirection: "column",
        px: 2,
        mb: 6
      }}
    >
      <Divider> {title} </Divider>
      <Box
        sx={{
          display: "flex",
          flexDirection: "column",
          mt: 1,
          px: 4,
          gap: 1
        }}
      >
        {children}
      </Box>
    </Box>
  );
}

function WebSetting({
  value,
  onChange
}: {
  value: CommonSettings;
  onChange: (v: CommonSettings) => void;
}) {
  const handleChange = (key: keyof CommonSettings, v: string | boolean) => {
    onChange({
      ...value,
      [key]: key === "port" && typeof v === "string" ? parseInt(v) : v
    });
  };

  return (
    <SettingLayout title="Web Server">
      <TextField
        label="address"
        variant="standard"
        type="number"
        onChange={(e) => handleChange("port", e.target.value)}
        value={value.port}
        sx={{ width: "120px" }}
      />
      <FormControlLabel
        control={
          <Checkbox
            size="small"
            onChange={(_, v) => handleChange("https", v)}
            checked={value.https}
          />
        }
        label="Enable Https"
      />

      <FileSelectInput
        label="Certificate"
        value={value.certFile}
        onChange={(v) => handleChange("certFile", v)}
      />
      <FileSelectInput
        label="Private Key"
        value={value.keyFile}
        onChange={(v) => handleChange("keyFile", v)}
      />
    </SettingLayout>
  );
}
function DatabaseSetting({
  value,
  onChange
}: {
  value: DBSettings;
  onChange: (v: DBSettings) => void;
}) {
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const key = e.target.name;
    const v = e.target.value;
    onChange({
      ...value,
      [key]: key === "port" && typeof v === "string" ? parseInt(v) : v
    });
  };

  return (
    <SettingLayout title="Database">
      <TextField
        sx={{ width: "300px" }}
        value={value.host}
        label="Host"
        variant="standard"
        name="host"
        onChange={handleChange}
      />
      <TextField
        sx={{ width: "300px" }}
        label="Port"
        value={value.port}
        variant="standard"
        name="port"
        type="number"
        onChange={handleChange}
      />
      <TextField
        sx={{ width: "300px" }}
        value={value.username}
        label="username"
        variant="standard"
        name="username"
        onChange={handleChange}
      />
      <TextField
        sx={{ width: "300px" }}
        value={value.password}
        label="password"
        variant="standard"
        name="password"
        onChange={handleChange}
      />
      <TextField
        sx={{ width: "300px" }}
        value={value.database}
        label="database"
        variant="standard"
        name="database"
        onChange={handleChange}
      />
    </SettingLayout>
  );
}

function VistaGatewaySetting({
  value,
  onChange
}: {
  value: GatewaySettings;
  onChange: (v: GatewaySettings) => void;
}) {
  const handleChange = (key: keyof GatewaySettings, v: string | boolean) => {
    onChange({
      ...value,
      [key]: v
    });
  };
  return (
    <SettingLayout title="Vista Gateway">
      <TextField
        size="small"
        label="Listen"
        variant="standard"
        type="number"
        value={value.listen}
        onChange={(e) => handleChange("listen", e.target.value)}
        sx={{ width: "120px" }}
      />
      <FormControlLabel
        control={
          <Checkbox size="small" checked={value.tls} onChange={(_, v) => handleChange("tls", v)} />
        }
        label="Enable TLS"
      />

      <FileSelectInput
        value={value.certFile}
        onChange={(v) => handleChange("certFile", v)}
        label="Certificate"
      />
      <FileSelectInput
        value={value.keyFile}
        onChange={(v) => handleChange("keyFile", v)}
        label="Private Key"
      />
    </SettingLayout>
  );
}
function LabGatewaySetting({
  value,
  onChange
}: {
  value: GatewaySettings;
  onChange: (v: GatewaySettings) => void;
}) {
  const handleChange = (key: keyof GatewaySettings, v: string | boolean) => {
    onChange({
      ...value,
      [key]: v
    });
  };
  return (
    <SettingLayout title="Lab Gateway">
      <TextField
        size="small"
        label="Listen"
        variant="standard"
        type="number"
        value={value.listen}
        onChange={(e) => handleChange("listen", e.target.value)}
        sx={{ width: "120px" }}
      />
      <FormControlLabel
        control={
          <Checkbox size="small" checked={value.tls} onChange={(_, v) => handleChange("tls", v)} />
        }
        label="Enable TLS"
      />

      <FileSelectInput
        value={value.certFile}
        onChange={(v) => handleChange("certFile", v)}
        label="Certificate"
      />
      <FileSelectInput
        value={value.keyFile}
        onChange={(v) => handleChange("keyFile", v)}
        label="Private Key"
      />
    </SettingLayout>
  );
}

function LogSetting({
  value,
  onChange
}: {
  value: LogSettings;
  onChange: (v: LogSettings) => void;
}) {
  const handleChange = (key: keyof LogSettings, v: string | boolean) => {
    onChange({
      ...value,
      [key]: typeof v === "string" ? parseInt(v) : v
    });
  };

  return (
    <SettingLayout title="Log">
      <TextField
        size="small"
        label="Max Size"
        variant="standard"
        value={value.maxSize}
        onChange={(v) => handleChange("maxSize", v.target.value)}
      />
      <TextField
        size="small"
        label="Max Backups"
        variant="standard"
        value={value.maxBackups}
        onChange={(v) => handleChange("maxBackups", v.target.value)}
      />
      <TextField
        size="small"
        label="Max Age"
        variant="standard"
        value={value.maxAge}
        onChange={(v) => handleChange("maxAge", v.target.value)}
      />
      <TextField
        size="small"
        label="Oper Max Size"
        variant="standard"
        value={value.operMaxSize}
        onChange={(v) => handleChange("operMaxSize", v.target.value)}
      />
      <FormControlLabel
        control={
          <Checkbox
            size="small"
            checked={value.compress}
            onChange={(_, v) => handleChange("compress", v)}
          />
        }
        label="Compress"
      />
    </SettingLayout>
  );
}

export default function SettingView() {
  const [form, setForm] = useState<Settings>();
  const [open, setOpen] = useState(false);

  useEffect(() => {
    const load = async () => {
      const configs = await invoke<Settings>(command.load_settings);
      setForm({ ...configs });
    };
    load();
  }, []);

  const handleChange = (v: SettingValue, key: SettingKey) => {
    const value = form as Settings;
    setForm({
      ...value,
      [key]: v
    });
  };

  const handleSubmit = async () => {
    await invoke<Settings>(command.save_settings, { configs: { ...form } });
    setOpen(true);
  };

  return (
    <>
      <OverlayScrollbarsComponent
        style={{ height: "100%", flex: 1, position: "relative" }}
        defer
        options={{
          scrollbars: { autoHide: "leave" },
          overflow: { x: "hidden", y: "scroll" }
        }}
      >
        <Box sx={{ px: 4, fontSize: "20px", fontWeight: 600 }}>Settings</Box>
        {form && (
          <Box sx={{ width: "90%", mx: "auto" }}>
            <SettingLayout title="General">
              <FormControlLabel
                control={
                  <Checkbox
                    size="small"
                    onChange={(_, v) => handleChange(v, "autoStart")}
                    checked={form.autoStart}
                  />
                }
                label="Auto Start"
              />
              <FormControlLabel
                control={
                  <Checkbox
                    size="small"
                    onChange={(_, v) => handleChange(v, "autoUpdate")}
                    checked={form.autoUpdate}
                  />
                }
                label="Auto Update"
              />
            </SettingLayout>
            <WebSetting value={form.app} onChange={(v) => handleChange(v, "app")} />
            <VistaGatewaySetting
              value={form.gateway}
              onChange={(v) => handleChange(v, "gateway")}
            />
            <LabGatewaySetting value={form.lab} onChange={(v) => handleChange(v, "lab")} />
            <DatabaseSetting value={form.db} onChange={(v) => handleChange(v, "db")} />
            <LogSetting value={form.log} onChange={(v) => handleChange(v, "log")} />
          </Box>
        )}

        <Box
          sx={{
            position: "sticky",
            backgroundColor: "#fefefe",
            bottom: 0,
            width: "100%",
            display: "flex",
            justifyContent: "end",
            p: 2
          }}
        >
          <Button variant="contained" onClick={handleSubmit}>
            Save
          </Button>
        </Box>
      </OverlayScrollbarsComponent>
      <Toast open={open} onClose={() => setOpen(false)} message="Save success!" />
    </>
  );
}
